/**
 * @widoc $.fn.initDropList
 * @namespace comp
 * @des 初始化单选下拉列表，调用此方法的文本框不需定义 name，即使定义也不可与 opts.name 相同
 * @type function
 * @param {object} opts 配置项
 * @param {string} opts.name 必须，下拉框中复选/单选元素的 name 属性值，初始化完成后，会在 el 后生成 <input type="hidden" name="name" />，以便表单取值
 * @param {object} opts.filter
 * @param {string|Array} opts.filter.fields 要检索的键
 * @param {boolean} opts.filter.pySupport 是否支持拼音首字过滤，开启过滤时，默认为 true
 * @param {string=} opts.filter.placeholder 过滤搜索框占位符(不支持IE8,9)
 * @param {Array} opts.data 必须，选项数据源
 * @param {string=} opts.txtField data 中每个数据显示的字段名称，默认为 'name'
 * @param {string=} opts.valField data 中每个数据值的字段名称，默认为 'val'
 * @param {int=} opts.width 弹出框的宽度，单位：px，默认为 205（css 中由.dropSel 决定）
 * @param {int=} opts.maxCount 最多显示几条记录，默认为 5
 * @param {Array=} opts.selParams 默认选中项条件 [key,value]
 * @param {function(selData)=} opts.callback 值改变时的回调方法
 * - selData 选中项的数据对象，无选中则为 undefined
 * @param {object} opts.dpOpts 下拉弹出框的初始参数，参考 $.fn.dropdown(opts)
 *       其中部分参数默认值不同：
 *         opts.dpOpts.modal 默认值为 false，即默认为非模态下拉框。
 *       其中部分参数失效：
 *         opts.dpOpts.cont 组件自动生成
 *         opts.dpOpts.noDestroy 始终为 true
 *         opts.dpOpts.show 始终为 false
 *         opts.dpOpts.beforeClose 组件中处理
 *         opts.dpOpts.beforeShow 组件中处理
 * @return {object} obj 返回对象
 * @rtn {object} obj.setData(data,selParams) 重置数据源及默认选中项
 * @rtn {object} obj.getSelect() 获取选中项，返回值：selData 选中项的数据对象，无选中则为 undefined
 * @rtn {object} obj.check(key,val) 选中符合条件的数据
 *       key {string=} 键
 *       val {string|undefined=} 值
 */
$.fn.initDropList=function(opts){
    var CONF={
        dplistLiH:25
    };
    var el=$(this);// 触发下拉的元素
    opts=$.extend({
        //            filter:{} // 显示检索框，其他接口后续开放
        //            ,name:'' // 必须，下拉框中复选/单选元素的 name 属性值，初始化完成后，会在 el 后生成 <input type="hidden" name="name" />，以便表单取值
        //width:0,// 弹出框的宽度
        maxCount:5 // 最多显示 5 条记录
        ,data:[] // 数据源
        ,txtField:'name' // data 中每个数据显示的字段名称
        ,valField:'val' // data 中每个数据值的字段名称
        ,dpOpts:{}// dropdown 扩展配置
        //        ,selParams: [key,value] // 第一次弹出的选中项条件[key,value]，value 支持数组
        //        ,callback: function(selData) // 确定按钮的回调，单选时为选中项的数据对象，无选中则为 undefined；多选时为选中对象数组，无选中则为 []
    },opts);
    var guid=$.generateGuid('dropSel');
    !opts.name && (opts.name=guid);
    var hideEl;// 隐藏元素，用于表单取值
    var _data,returnObj;// 返回对象
    var dpObj// dropdown 返回接口
        ,dpEl// 下拉弹出层 jquery 对象
        ,_filterObj
        ,selData;// 选中的项
    //        var keyword;// 记录当前关键字
    var _getSelect=function(){
        return selData;
    };
    // 只改变选中项，不修改文本框
    var _setSelData=function(item){
        selData=item;
        if(!item){
            hideEl.val('');
        }else{
            hideEl.val(item[opts.valField]);
        }
    };
    // 选中指定对象
    var _checkItem=function(item){
        _setSelData(item);
        if(!item){
            el.val('');
        }else{
            el.val(item[opts.txtField]);
        }
        opts.callback && opts.callback(item);
        if(opts.filter && _filterObj){
            _filterObj.filter(selData && selData[opts.txtField] ? selData[opts.txtField] : '');
        }
    };
    /**
     * 改变符合条件的数据源的选中状态，并更新到 dom 和 selIdx
     * @param key {string=} 键
     * @param val {string|undefined=} 值
     * @private
     */
    var _check=function(key,val){
        if(key){
            for(var i= 0,item;i<_data.length;i++){
                item=_data[i];
                if(item[key]==val){
                    _checkItem(item);
                    return;
                }
            }
        }
        _checkItem();// 默认清空选项
    };
    var visibleData;// 要显示的所有数据
    var curPage// 当前显示数据位于第几页（visibleData 中 0 开始）
        ,curIndex;// 当前高亮数据索引（visibleData 中 0 开始）
    var _setVisibleData=function(data){
        var toolEl=dpEl.find('.dropSel-tool');
        visibleData=data;
        if(visibleData.length>opts.maxCount){// 一页无法显示，启用翻页，不能隐藏，否则弹出后过滤可能造成高度变化
            toolEl.find('button').prop('disabled',false);
        }else{
            toolEl.find('button').prop('disabled',true);
        }
        _chargeList();
    };
    // 修改数据源并根据 selParams 重置默认选中值
    var _setData=function(data,selParams){
        if(data) _data= $.extend([],data);
        var str='';
        var txtField=opts.txtField;
        var valField=opts.valField;
        for(var i= 0,item;i<_data.length;i++){
            item=_data[i];
            str+='<li data-i="'+item[valField]+'">'+$.encodeHtml(item[txtField])+'</li>';
        }
        dpEl.find('ul.dplist-box').html(str);
        if(_filterObj){// 更新过滤组件数据源
            _filterObj.setData(_data);
        }
        if(data){// 重置数据源，需要同步更新选中项
            if(selParams){
                _check(selParams[0],selParams[1]);
            }else{
                _check();
            }
        }
    };
    // 根据 curPage 刷新当前显示的数据列表
    // selI 若未定义，则选中当页第一项
    var _chargeList=function(pageI,selI){
        dpEl.find('li').removeClass('now active');
        if(visibleData.length){
            var count=opts.maxCount;
            var valField=opts.valField;
            if(pageI==undefined){// 未定义页码
                pageI = selI!=undefined ? // 定义了高亮行则据此计算页码，否则为 0
                    Math.floor(selI/count) : 0;
            }
            curPage=pageI;
            var start = pageI*opts.maxCount// 开始索引
                ,end = Math.min(start+count,visibleData.length);// 结束索引
            if(selI==undefined || selI < start || selI > end){
                selI=start;
            }
            // 开始翻页及高亮处理
            for(var i=start,item;i<end;i++){
                item=visibleData[i];
                dpEl.find('li[data-i="'+item[valField]+'"]').addClass('now');
            }
        }else{
            curPage=undefined;
            selI=undefined;
        }
        _setActiveItem(selI);
    };
    var _setActiveItem=function(i){
        curIndex=i;
        if(curIndex!=undefined){
            dpEl.find('li[data-i="'+visibleData[curIndex][opts.valField]+'"]').addClass('active');
        }
        el.focus();
    };
    // 向前翻页
    var _flipPrev=function(){
        _chargeList(curPage>0 ? curPage-1 : Math.ceil(visibleData.length/opts.maxCount)-1);
    };
    // 向后翻页
    var _flipNext=function(){
        _chargeList(curPage < Math.ceil(visibleData.length/opts.maxCount)-1 ? curPage+1 : 0);
    };
    var _initDp=function(){
        var str='<div class="dropdown dropSel dropList">';
        var boxW=opts.width;
        str+='<div class="dropSel-box" style="'+(boxW?'width:'+boxW+'px;':'')+'height:'+(opts.maxCount*CONF.dplistLiH)+'px"><ul class="dplist-box"></ul></div>'+
            '<div class="dropSel-tool">' +
            '<button class="dropSel-btn" style="float:left;" data-val="prev">上页</button>'+
            '<button class="dropSel-btn" data-val="next">下页</button>'+
            '</div></div>';
        // 下拉框中的内容部分
        dpEl=$(str);
        dpEl
            .on('click.dpSel','.dropSel-tool [data-val]',function(){// 操作按钮
                if(!dpObj) return;
                var ctrlVal=$(this).attr('data-val');
                if(ctrlVal=='prev'){// 上一页
                    _flipPrev();
                }else if(ctrlVal=='next'){// 下一页
                    _flipNext();
                }
            })
            .on('click.choose','li',function(){// 点选数据
                _check(opts.valField, $(this).attr('data-i'));
                dpObj.close();
            });
        dpObj=el.dropdown($.extend(
            {
                modal: false
            },
            opts.dpOpts,
            {
                cont: dpEl,
                noDestroy: true,
                show: false,
                beforeShow:function(){
                    opts.filter && _setVisibleData(_data);
                },
                beforeClose: function(){
                    if(!selData || el.val() != selData[opts.txtField]) _checkItem();// 值与当前选中项不匹配，置空
                }
            }
        ));
    };
    var _init=function(){
        hideEl=$('<input type="hidden" name="'+opts.name+'" />');
        el.attr('autocomplete','off')
          .after(hideEl);// 添加隐藏域
        _initDp();
        _setData(opts.data);
        el.prop('readonly',!opts.filter);// 支持过滤时允许写入
        if(opts.filter){
            !opts.filter.fields && (opts.filter.fields=opts.txtField);
            _filterObj=el.initFilter($.extend({// 打开前需手动过滤
                data:_data
                ,afterFilter:function(newData,keyword){
                    if(selData && selData[opts.txtField].toLocaleUpperCase()!=keyword){
                        _setSelData();// 置空
                    }
                    _setVisibleData(newData);
                }
            },opts.filter));
        }else{
            _setVisibleData(_data);
        }
        var selParams=opts.selParams;
        if(selParams){
            _check(selParams[0],selParams[1]);
        }else{
            _check();
        }
        el.off('click.showDp').on('click.showDp',function(){
            if(!dpObj) return;
            if(opts.filter){// 点击显示列表
                !dpObj.isShown() && dpObj.show();
            }else{// 不支持过滤时，点击切换显示状态
                dpObj.isShown() ? dpObj.close() : dpObj.show();
            }
        });
        el.off('keydown.dpList').on('keydown.dpList',function(e){// 文本框的键盘监听
            var which= e.which;
            if(!dpObj) return;
            if(which==13){// 回车
                if(dpObj.isShown()){
                    _checkItem(visibleData[curIndex]);
                    dpObj.close();
                }else{
                    dpObj.show();
                }
            }else if(which==9){// 失焦关闭
                if(dpObj.isShown()){
                    dpObj.close();
                }
            }else{
                if(!dpObj.isShown()){
                    dpObj.show();
                }else{
                    if (which == 38) {// 上
                        _chargeList(undefined, curIndex == 0 ? visibleData.length - 1 : curIndex - 1);
                        e.preventDefault();
                    } else if (which == 40) {// 下
                        _chargeList(undefined, curIndex == visibleData.length - 1 ? 0 : curIndex + 1);
                        e.preventDefault();
                    }
                }
            }
        });
    };
    returnObj={
        getSelect:_getSelect,// 获取选中值，单选时返回对象，多选时返回数组
        check:_check,// 改变符合条件的数据源的选中状态，并更新到 dom 和 selIdx
        setData:_setData// 重置数据源
    };
    _init();
    return returnObj;
};